package Modele;

import java.awt.*;
import java.util.List;
import java.util.Random;
import java.sql.Date;
import java.util.ArrayList;
import java.util.concurrent.Callable;
import java.util.concurrent.ExecutionException;
import java.util.concurrent.ExecutorService;
import java.util.concurrent.Executors;
import java.util.concurrent.Future;

public class MyCallable implements Callable<Double>  {
	
	private String CallPutFlag;
	private double S; 
	private double X;
	private double r;
	private double T; 
	private double b; 
	private double v; 
	private int nSteps; 
	private int nSimulations;
	
	private  double resultat=5;
	
	private double res;

	@Override
	public synchronized  Double call() throws Exception {

		double dt;
		double St;
		double Sum=0;
		double Drift; 
		double vSqrdt;
		
		int z=0;
		Random rand=new Random();
		
		
		dt = T / nSteps;
		Drift = (b - v*v / 2) * dt;
		vSqrdt = v * java.lang.Math.sqrt(dt);
		if ("call".equals(CallPutFlag)){
			z=1; 
		}
		else if ("putt".equals(CallPutFlag)){
			z=-1; 
		}
		//for (int k=1; k<=nSimulations; k++){
			St = S; 
			
			for (int l=1; l<=nSteps; l++){
				St = St * (java.lang.Math.exp(Drift + vSqrdt *rand.nextGaussian())); 
				
			}
			Sum = Sum + java.lang.Math.max(z*(St-X), 0); 
			
			res=(java.lang.Math.exp((-r*T))*(Sum/nSimulations)); 
			
		
		//}
		
		
		double result = (java.lang.Math.exp((-r*T))*(Sum/nSimulations)); 
		System.out.println("res final "+result);
		
		
		
		
		
		resultat = result;
        return resultat;
	}
	
	public void mycall(){
		
		int proc = Runtime.getRuntime().availableProcessors();
		
		System.out.println("Nombre de coeur : "+proc);
		
		//Get ExecutorService from Executors utility class, thread pool size is 10
        ExecutorService executor = Executors.newFixedThreadPool(proc);
        //create a list to hold the Future object associated with Callable
        
        List<Future<Double>> list = new ArrayList<Future<Double>>();
        
        //Create MyCallable instance
        
        Callable<Double> callable = new MyCallable();
        
        for(int i=0; i< nSimulations; i++){
            //submit Callable tasks to be executed by thread pool
            Future<Double> future = executor.submit(callable);
            //add Future to the list, we can get return value using Future
            list.add(future);
        }
        
        for(Future<Double> fut : list){
            try {
                //print the return value of Future, notice the output delay in console
                // because Future.get() waits for task to get completed
            	
            	res = res +fut.get();
                System.out.println("resultat : "+fut.get());
                System.out.println("resultat final : "+res);
                
            } catch (InterruptedException | ExecutionException e) {
                e.printStackTrace();
            }
        }
        //shut down the executor service now
        executor.shutdown();
    }
	
	

	public void getAll(String callPutFlag, double s, double x, double r,
			double t, double b, double v, int nSteps,
			int nSimulations) {
		
		this.CallPutFlag = callPutFlag;
		this.S=s;
		this.X=x;
		this.r=r;
		this.T=t;
		this.b=b;
		this.v=v;
		this.nSteps=nSteps;
		this.nSimulations=nSimulations;
	
	}
    }
		
		
	
	
	
	
	
	


